package com.alstudio.module.xmpp.distributor.versioncheck;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.Socket;

import org.xmlpull.v1.XmlPullParserException;

import android.os.AsyncTask;
import android.text.TextUtils;

import com.alstudio.module.xmpp.distributor.distributor.DistributorEventListener;
import com.alstudio.pojo.module.server.ServerInfo;
import com.alstudio.pojo.module.server.Serverlet;
import com.alstudio.utils.android.net.AndroidNetUtils;
import com.alstudio.utils.log.ALLog;
import com.alstudio.utils.xml.BaseXmlParser;
import com.alstudio.utils.xml.XmlParseEventHandler;

public class VersionCheckUtils {

	private static VersionCheckUtils instance;
	// 版本号节点
	private final String VERSION_TAG = "version";
	// IM服务器节点
	private final String IM_SERVER_TAG = "imserver";
	// 媒体服务器节点
	private final String MEDIA_SERVER_TAG = "mediaserver";
	// 充值服务器节点
	private final String CHARGE_SERVER_TAG = "extendcharge";
	// 充值服务器节点
	private final String CHARGE_SERVER_TAG2 = "extendcharge2";
	// 其他服务器器节点
	private final String EXTEND_OTHER_SERVER_TAG = "extendother";
	// 积分商城节点
	private final String POINT_MARKET_SERVER_TAG = "pointmarket";
	// php任务服务器
	private final String TASK_PHP_SERVER_TAG = "taskphp";
	// java任务服务器
	private final String TASK_JAVA_SERVER_TAG = "taskjava";
	// 启动界面下载地址
	private final String WELCOME_URL_TAG = "welcomeurl";
	// 启动界面版本
	private final String WELCOME_VER_TAG = "welcomever";

	private NewVersionListener mVersionCheckListener;
	private DistributorEventListener mDistributorListener;

	public static VersionCheckUtils getInstance() {
		if (instance == null) {
			instance = new VersionCheckUtils();
		}
		return instance;
	}

	public void setNewVersionAlertListener(NewVersionListener listener) {
		mVersionCheckListener = listener;
	}

	public void setDistributorEventListener(DistributorEventListener listener) {
		mDistributorListener = listener;
	}

	private CheckNewVersionResult checkNewVersionByHttp(String ip, String port,
			String msg, boolean isForVersionCheck) {
		HttpURLConnection conn = null;
		InputStream in = null;
		CheckNewVersionResult result = null;
		String errorMessage = null;
		BufferedReader reader = null;
		try {

			String requestUrl = "http://" + ip + ":" + port + "/";
			conn = AndroidNetUtils.buildHttpUrlConnectionUsingGetMethod(
					requestUrl, null);

			ALLog.d("write to server: " + msg);

			conn.getOutputStream().write(msg.getBytes());

			in = conn.getInputStream();

			reader = new BufferedReader(new InputStreamReader(in));
			String s = ""/* ALFileManager.copyToString(reader) */;

			String xml = "";
			while ((s = reader.readLine()) != null) {
				// System.out.println(line);
				xml += s;
				if (xml.contains("/dispatcher")) {
					break;
				}
			}
			ALLog.d("read from server: " + xml);

			result = parseCheckVersionResult(xml, isForVersionCheck);
			// result = parseCheckVersionResult(in, isForVersionCheck);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			errorMessage = e.toString();
		} finally {

			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if (conn != null) {
				conn.disconnect();
			}

			try {

				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		if (result == null) {
			result = new CheckNewVersionResult();
			result.setIsSuccessed(false);
			result.setErrorMessage(errorMessage);
		}
		return result;
	}

	private CheckNewVersionResult checkNewVersionBySocket(String ip,
			String port, String msg, boolean isForVersionCheck) {
		Socket socket = null;
		InputStream in = null;
		CheckNewVersionResult result = null;
		String errorMessage = null;
		BufferedReader reader = null;

		try {
			socket = AndroidNetUtils.buildSocketConnection(ip, port);

			socket.getOutputStream().write(msg.getBytes());

			in = socket.getInputStream();
			reader = new BufferedReader(new InputStreamReader(in));

			String s = "";

			String xml = "";
			while ((s = reader.readLine()) != null) {
				// System.out.println(line);
				xml += s;
				if (xml.contains("/dispatcher")) {
					break;
				}
			}
			ALLog.d("read from server: " + xml);

			result = parseCheckVersionResult(xml, isForVersionCheck);
			// result = parseCheckVersionResult(in, isForVersionCheck);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			errorMessage = e.toString();

		} finally {

			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			if (socket != null) {
				try {
					if (socket != null) {
						socket.close();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			try {

				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (result == null) {
			result = new CheckNewVersionResult();
			result.setIsSuccessed(false);
			result.setErrorMessage(errorMessage);
		}
		return result;
	}

	public void checkVersion(String ip, String port, String msg,
			boolean bySocket, boolean isForVersionCheck) {

		if (TextUtils.isEmpty(ip)) {
			throw new IllegalArgumentException("ip address should not null");
		}

		if (TextUtils.isEmpty(port)) {
			throw new IllegalArgumentException("port should not null");
		}

		if (!TextUtils.isDigitsOnly(port)) {
			throw new IllegalArgumentException(
					"port should just need digits only");
		}

		CheckVersionParam param = new CheckVersionParam();
		param.setDispUrl(ip);
		param.setPort(port);
		param.setWriteMsg(msg);
		param.checkBySocket(bySocket);
		param.setIsForVersionCheck(isForVersionCheck);
		new CheckVesionTask().execute(param);
	}

	public void notifyNewVersionArraived(CheckNewVersionResult result) {

		if (result.isForVersionCheck()) {
			if (mVersionCheckListener != null) {
				if (result.isSuccessed() && result.isFillValue()) {
					mVersionCheckListener.onNewVersionArraived(result.getServerInfo());
				} else {
					mVersionCheckListener.onCheckNewVersionFailed(result
							.getErrorMessage());
				}
			}
		} else {
			// 链接分发器
			if (mDistributorListener != null) {
				if (result.isSuccessed()) {
					mDistributorListener.onCheckDistributorSuccess(result
							.getServerInfo());
				} else {
					mDistributorListener.onCheckDistributorFailed(result
							.getErrorMessage());
				}
			}
		}

	}

	private CheckNewVersionResult parseCheckVersionResult(InputStream in,
			boolean isForVersionCheck) throws XmlPullParserException,
			IOException {
		CheckNewVersionResult result = new CheckNewVersionResult();
		VersionCheckParser parser = new VersionCheckParser(in,
				isForVersionCheck);
		result = parser.start();
		result.setIsForVersionCheck(isForVersionCheck);
		return result;
	}

	private CheckNewVersionResult parseCheckVersionResult(String xml,
			boolean isForVersionCheck) throws XmlPullParserException,
			IOException {
		CheckNewVersionResult result = new CheckNewVersionResult();
		VersionCheckParser parser = new VersionCheckParser(xml,
				isForVersionCheck);
		result = parser.start();
		result.setIsForVersionCheck(isForVersionCheck);
		return result;
	}

	private class CheckVesionTask extends
			AsyncTask<CheckVersionParam, Void, CheckNewVersionResult> {

		@Override
		protected void onPostExecute(CheckNewVersionResult result) {
			// TODO Auto-generated method stub
			super.onPostExecute(result);
			notifyNewVersionArraived(result);
		}

		@Override
		protected CheckNewVersionResult doInBackground(
				CheckVersionParam... params) {
			// TODO Auto-generated method stub
			ALLog.d("start version check...");
			CheckVersionParam param = params[0];
			if (param.isCheckBySocket()) {
				return checkNewVersionBySocket(param.getDispUrl(),
						param.getPort(), param.getWriteMsg(),
						param.isForVersionCheck());
			} else {
				return checkNewVersionByHttp(param.getDispUrl(),
						param.getPort(), param.getWriteMsg(),
						param.isForVersionCheck());
			}
		}
	}

	private class CheckVersionParam {
		private String msg;
		private boolean checkBySocket;
		private String url;
		private String port;
		private boolean isForVersionCheck = false;

		public void setIsForVersionCheck(boolean c) {
			this.isForVersionCheck = c;
		}

		public boolean isForVersionCheck() {
			return this.isForVersionCheck;
		}

		public void setWriteMsg(String msg) {
			this.msg = msg;
		}

		public String getWriteMsg() {
			return this.msg;
		}

		public void checkBySocket(boolean bySocket) {
			this.checkBySocket = bySocket;
		}

		public boolean isCheckBySocket() {
			return this.checkBySocket;
		}

		public void setDispUrl(String url) {
			this.url = url;
		}

		public String getDispUrl() {
			return this.url;
		}

		public void setPort(String p) {
			this.port = p;
		}

		public String getPort() {
			return this.port;
		}
	}

	private class VersionCheckParser extends BaseXmlParser {

		private boolean isForVersionCheck = false;

		public VersionCheckParser(InputStream in, boolean isForVersionCheck)
				throws XmlPullParserException {
			// TODO Auto-generated constructor stub
			createParser(in);
			this.isForVersionCheck = isForVersionCheck;
		}

		public VersionCheckParser(String xml, boolean isForVersionCheck)
				throws XmlPullParserException {
			// TODO Auto-generated constructor stub
			createParser(xml);
			this.isForVersionCheck = isForVersionCheck;
		}

		protected CheckNewVersionResult start() throws XmlPullParserException,
				IOException {
			VersionCheckXmlParseEventHandler handler = new VersionCheckXmlParseEventHandler(
					this, isForVersionCheck);
			setXmlParseCallback(handler);
			handler.startParse();
			return handler.getResult();
		}

	}

	private class VersionCheckXmlParseEventHandler extends XmlParseEventHandler {
		CheckNewVersionResult result = null;

		ServerInfo info = new ServerInfo();

		boolean isForCheckVersion = false;

		public VersionCheckXmlParseEventHandler(BaseXmlParser parser,
				boolean isForCheckVersion) {
			super(parser);

			this.isForCheckVersion = isForCheckVersion;
		}

		public CheckNewVersionResult getResult() {

			if (result == null) {
				result = new CheckNewVersionResult();
				result.setIsFillValue(false);
				result.setIsSuccessed(false);
				result.setErrorMessage("faile to parse xml");
			} else {
				result.setIsFillValue(true);
				result.setIsSuccessed(true);
			}

			// result.setIsFillValue(true);
			result.setIsSuccessed(true);

//			if (!isForCheckVersion) 
			{
				result.setServerInfo(info);
			}
			return result;
		}

		@Override
		public void processStartTag(String tag) {
			// TODO Auto-generated method stub
			if (VERSION_TAG.equals(tag)) {
				// 版本更新
				result = new CheckNewVersionResult();
				// 新版本下载连接
				result.setLatestVer(getAttValue("ver"));
				result.setNewVersionUrl(getAttValue("url"));

				String tmp = getAttValue("mustupdate");
				if (!TextUtils.isEmpty(tmp)) {
					// 强制更新
					if (tmp.equals("1")) {
						result.setForceUpdateState(true);
					}
				}
				result.setWhatsNew(processText(tag));
				info.setLatestVer(result.getLatestVer());
				info.setNewVersionUrl(result.getNewVersionUrl());
				info.setForceUpdateState(result.isForceUpdate());
				info.setWhatsNew(result.getWhatsNew());

			} else if (IM_SERVER_TAG.equals(tag)) {
				// IM服务器节点
				info.setIMServerIP(getAttValue("ip"));
				info.setIMSocketPort(getAttValue("port"));
			} else if (MEDIA_SERVER_TAG.equals(tag)) {
				// 媒体服务器节点
				info.setMediaServerIp(getAttValue("ip"));
				info.setMediaServerPort(getAttValue("port"));
			} else if (CHARGE_SERVER_TAG.equals(tag)) {
				// 充值服务器
				info.setExtendChargeUrl(getAttValue("url"));
				info.setChargeCallbackUrl(info.getExtendChargeUrl()
						+ Serverlet.YEE_PAY_SERVERLET_SUFIX);
				info.setAlipayUrl(info.getExtendChargeUrl()
						+ Serverlet.ALIPAY_SERVERLET_SUFIX);

			} else if (CHARGE_SERVER_TAG2.equals(tag)) {
				// 充值服务器2
				info.setExtendChargeUrl(getAttValue("url"));
				info.setChargeCallbackUrl(info.getExtendChargeUrl()
						+ Serverlet.YEE_PAY_SERVERLET_SUFIX);
				info.setAlipayUrl(info.getExtendChargeUrl()
						+ Serverlet.ALIPAY_SERVERLET_SUFIX);
			} else if (tag.equals(WELCOME_URL_TAG)) {
				info.setSplashUrl(getAttValue("url"));
				ALLog.d("启动界面URL" + info.getSplashUrl());
			} else if (tag.equals(WELCOME_VER_TAG)) {
				info.setSplashVersion(getAttValue("url"));
				ALLog.d("启动界面版本" + info.getSplashVersion());
			} else if (tag.equals(EXTEND_OTHER_SERVER_TAG)) {
				info.setExtendOther(getAttValue("url"));
			} else if(TASK_PHP_SERVER_TAG.equals(tag)){
				//完成任务
				info.setTaskPhp(getAttValue("url"));
			} else if(TASK_JAVA_SERVER_TAG.equals(tag)){
				info.setTaskJava(getAttValue("url"));
			}
		}

		@Override
		public void processEndTag(String tag) {
			// TODO Auto-generated method stub

		}

		@Override
		public void processStartDocument() {
			// TODO Auto-generated method stub

		}

		@Override
		public void processEndDocument() {
			// TODO Auto-generated method stub
		}

	}

}
